﻿//TODO: Dilation: test

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// 
    /// </summary>
    public class Dilation : BaseForeBackgroundColorFilter
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Dilation"/> class.
        /// </summary>
        public Dilation()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Dilation"/> class.
        /// </summary>
        /// <param name="_dilation">The _dilation.</param>
        internal Dilation(Dilation _dilation)
        {
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            // Create Destination bitmap.
            UnsafeBitmap tempbmp = _bitmap;
            // Take source bitmap data.
            BitmapData SrcData = _bitmap.BitmapData; //SrcImage.LockBits(new Rectangle(0, 0,SrcImage.Width, SrcImage.Height), ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb);
            // Element array to used to dilate.
            byte[,] sElement = new byte[5, 5] {
                {0,0,1,0,0},
                {0,1,1,1,0},
                {1,1,1,1,1},
                {0,1,1,1,0},
                {0,0,1,0,0}
            };

            // Element array size.
            int size = 5;
            byte max, clrValue;
            int radius = size / 2;
            int ir, jr;

            unsafe
            {
                // Loop for Columns.
                for (int colm = radius; colm < SrcData.Height - radius; colm++)
                {
                    // Initialise pointers to at row start.
                    byte* ptr = (byte*)SrcData.Scan0 + (colm * SrcData.Stride);
                    byte* dstPtr = (byte*)SrcData.Scan0 + (colm * SrcData.Stride);
                    // Loop for Row item.
                    for (int row = radius; row < SrcData.Width - radius; row++)
                    {
                        max = 0;
                        clrValue = 0;
                        // Loops for element array.
                        for (int eleColm = 0; eleColm < 5; eleColm++)
                        {
                            ir = eleColm - radius;
                            byte* tempPtr = (byte*)SrcData.Scan0 +
                            ((colm + ir) * SrcData.Stride);
                            for (int eleRow = 0; eleRow < 5; eleRow++)
                            {
                                jr = eleRow - radius;
                                // Get neightbour element color value.
                                clrValue = (byte)((tempPtr[row * 3 + jr] + tempPtr[row * 3 + jr + 1] + tempPtr[row * 3 + jr + 2]));
                                if (max < clrValue)
                                {
                                    if (sElement[eleColm, eleRow] != 0)
                                        max = clrValue;
                                }
                            }
                        }
                        dstPtr[0] = dstPtr[1] = dstPtr[2] = max;
                        ptr += 3;
                        dstPtr += 3;
                    }
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new Dilation(this);
        }
    }
}

